package nameless.aistudy.common.util.jwt;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * JWT (JSON Web Token) 工具类
 * 用于生成、解析和验证 JWT
 */
@Component
public class JwtUtil {

    /**
     * JWT 密钥
     * 重要：这是一个示例密钥，生产环境中必须使用一个安全、随机且足够长的密钥！
     * 你可以使用 jjwt 提供的工具生成：Keys.secretKeyFor(SignatureAlgorithm.HS256)
     * 或者从配置文件中读取。
     */
    private static final String SECRET = "ThisIsASecretKeyForJWTTokenGenerationAndVerification123456789";
    private static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());

    /**
     * Token 过期时间：24小时
     * 单位：毫秒
     */
    private static final long EXPIRATION = 1000 * 60 * 60 * 24;

    /**
     * 生成 JWT Token
     *
     * @param userId 用户ID，作为 Token 的 subject
     * @param claims 额外的自定义声明 (例如：角色、权限等)，可以为 null
     * @return 生成的 JWT 字符串
     */
    public static String generateToken(String userId, Map<String, Object> claims) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + EXPIRATION);

        return Jwts.builder()
                .subject(userId) // 设置主题，这里使用用户ID
                .issuedAt(now)   // 设置签发时间
                .expiration(expiryDate) // 设置过期时间
                .claims(claims) // 添加自定义声明
                .signWith(KEY) // 使用密钥进行签名
                .compact();
    }

    /**
     * 生成不带额外声明的 JWT Token
     *
     * @param userId 用户ID
     * @return 生成的 JWT 字符串
     */
    public static String generateToken(String userId) {
        return generateToken(userId, null);
    }

    /**
     * 从 Token 中解析出 Claims
     *
     * @param token JWT 字符串
     * @return Claims 对象，包含所有声明
     * @throws JwtException 如果 Token 无效（签名错误、格式错误等）
     * @throws ExpiredJwtException 如果 Token 已过期
     */
    private static Claims parseClaims(String token) {
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    /**
     * 从 Token 中解析出用户ID (subject)
     *
     * @param token JWT 字符串
     * @return 用户ID
     * @throws JwtException 如果 Token 无效
     * @throws ExpiredJwtException 如果 Token 已过期
     */
    public static String getUserIdFromToken(String token) {
        return parseClaims(token).getSubject();
    }

    /**
     * 验证 Token 是否有效
     *
     * @param token JWT 字符串
     * @return 如果 Token 有效（未过期且签名正确）则返回 true，否则返回 false
     */
    public static boolean validateToken(String token) {
        try {
            parseClaims(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 检查 Token 是否即将过期（例如：在1小时内过期）
     *
     * @param token JWT 字符串
     * @param thresholdMillis 指定时间
     * @return 如果 Token 在指定时间内过期则返回 true
     */
    public static boolean isTokenExpiredWithin(String token, long thresholdMillis) {
        try {
            Claims claims = parseClaims(token);
            Date now = new Date();
            return claims.getExpiration().getTime() - now.getTime() < thresholdMillis;
        } catch (JwtException e) {
            // 如果 Token 本身无效，则视为“即将过期”以强制用户重新登录
            return true;
        }
    }

    /**
     * 获取 Token 的过期时间
     *
     * @param token JWT 字符串
     * @return 过期时间的 Date 对象
     */
    public static Date getExpirationDateFromToken(String token) {
        return parseClaims(token).getExpiration();
    }
}

